package com.game.NioSocket;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 事物处理
 * @author CHENLEI
 *
 */
public class Gsocket {
	public final ConcurrentLinkedQueue<byte[]> HandleBuffers = new ConcurrentLinkedQueue<byte[]>();
	public final ConcurrentLinkedQueue<ByteBuffer> writeBuffers = new ConcurrentLinkedQueue<ByteBuffer>();
	public SocketChannel channel;
	
	private SelectionKey key;////在 Selector 中的注册的标记
	private ByteBuffer buffer=null;

	private int result=0;           //读取数量
	private int packLen=0;// 包长
	
	public Gsocket(SocketChannel channel){
		this.channel=channel;
		buffer=ByteBuffer.allocateDirect(1024);
	}
	/**
	 * 读取数据，
	 * @param channel
	 * @throws Exception 
	 */
	public synchronized void ReadData(){
		try {
			result=channel.read(buffer);
			buffer.flip();
			if(result>0){//返回-1，到流的末尾，但是通道还是保持链接；
				//判断是否获取下一个包的包长
				while(buffer.hasRemaining()){
					if(this.packLen<1){
						this.packLen=buffer.get()+129;
					}
					
					if(buffer.remaining()>=packLen){
						byte[]pack=new byte[packLen];
						buffer.get(pack, 0, packLen);
						System.out.println("packLen:"+  packLen);
						System.out.println("recive data:"+ new String(pack, 0, packLen));
						this.getHandleBuffers().add(pack);
						packLen=0;
					}else{
						//不够一个包长，跳出当前循环
						break;
					}
				}
				buffer.compact();
			}else{
				//读取信息异常，通道断开
				shutdown(this);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("客户端:"+ this.getChannel().socket().getRemoteSocketAddress()+"下线");
			/**
			 * 下线对象的销毁
			 */
			
			shutdown(this);
		}
	
	}
	
	/**
	 * 将应用逻辑处理完毕的数据添加到待发送的队列
	 *   标记通道可写
	 * @param buffer
	 */
	public void writeData(ByteBuffer buffer){
		writeBuffers.add(buffer);
		if(key.isValid()){
			key.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE);
			key.selector().wakeup();
		}
	}
	/**
	 * 判断是否有可发送的数据
	 * @return
	 */
	public boolean HaveData(){
		return !writeBuffers.isEmpty();
	}
	/***
	 *  发送处理后的数据
	 * @param channel
	 * @throws IOException 
	 */
	public synchronized void SendData() throws IOException{
		ByteBuffer buffer;
		while(!writeBuffers.isEmpty()){
			buffer=writeBuffers.poll();
			while(buffer.remaining()>0){
				channel.write(buffer);
			}
		}
		key.interestOps(SelectionKey.OP_READ);//标记通道可读就绪
	}
	/**
	 * @throws IOException 
	 * 
	 */
	public void Regiester(Selector selector) throws IOException{
		
		/**
		 * 设置为非阻塞模式，参与事件驱动的
		 */
		this.channel.configureBlocking(false);
		key=this.channel.register(selector, SelectionKey.OP_READ, this);//标记通道可读就绪（做好准备）
	}
	
	/**
	 *  判断通道的状态
	 * @return
	 */
	public synchronized final boolean isOpen(){
		return getChannel().isOpen();
	}
	
	public  synchronized final SocketChannel getChannel() {
		if(channel!=null)
		return channel;
		return null;
	}
	
	public void shutdown(Gsocket gsocket){
		try {
			key.cancel();
			channel.close();
			HandleBuffers.clear();
			writeBuffers.clear();
		/**
		 * 回写数据，销毁对象
		 */
		--dispatcher.countNum;
		} catch (IOException e) {
			
		}
	}
	public ConcurrentLinkedQueue<byte[]> getHandleBuffers() {
		return HandleBuffers;
	}
	
	


	
}
